package com.wang.sqlsession;

import com.wang.pojo.Configuration;
import com.wang.pojo.MappedStatement;


import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by wangq on 2021/7/1.
 */
public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public void create(String statementId, Object... objects) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        simpleExecutor.create(configuration, mappedStatement, objects);
    }

    @Override
    public void update(String statementId, Object... objects) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        simpleExecutor.update(configuration, mappedStatement, objects);
    }

    @Override
    public void delete(String statementId, Object... objects) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        simpleExecutor.delete(configuration, mappedStatement, objects);
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... objects) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        return simpleExecutor.query(configuration, mappedStatement, objects);

    }

    @Override
    public <T> T selectOne(String statementId, Object... objects) throws Exception {
        List<T> resultList = selectList(statementId, objects);
        if (resultList.size() > 1) {
            throw new RuntimeException("查询结果大于1个");
        } else if (resultList.size() == 1) {
            return resultList.get(0);
        } else {
            throw new RuntimeException("查询结果为空");
        }
    }


    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        // 使用JDK动态代理为Dao接口生成代理对象
        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, (proxy, method, args) -> {
            //1、获取statementId = nameSpace.id = 接口全限定名.方法名
            String className = method.getDeclaringClass().getName(); // 类名称
            String methodName = method.getName();// 获取方法名
            String statementId = className + "." + methodName;
            MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);

            SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
            switch (sqlCommandType) {
                case INSERT:
                    create(statementId, args);
                    break;
                case UPDATE:
                    update(statementId, args);
                    break;
                case DELETE:
                    delete(statementId, args);
                    break;
                case SELECT:
                    // 判断返回值是否有泛型
                    if (method.getGenericReturnType() instanceof ParameterizedType) {
                        // 有泛型就查询列表
                        return selectList(statementId, args);
                    } else {
                        // 无泛型就查询单个
                        return selectOne(statementId, args);
                    }
                default:
                    throw new Exception("无效的数据操作类型");
            }
            return proxy;
        });
        return (T) proxyInstance;
    }


}
